﻿using System;
using System.Linq;
using System.Collections;
using System.Security.Principal;
using System.Collections.Generic;
using System.Text;
using SilenthinkContract.Domain;
using SilenthinkCommon.Extension;

namespace Web.Components
{
    public enum ShoppingCartOperate
    {
        UpdateQuantity = 0,
        Remove = 1,
        Clear = 2
    }
    public sealed class ShoppingCart
    {
        private readonly Hashtable cartItems = Hashtable.Synchronized(new Hashtable());
        public static readonly ShoppingCartConfig Config = new ShoppingCartConfig(false, false);

        /// <summary>
        /// 用户
        /// </summary>
        public IIdentity Identity { get; set; }
        /// <summary>
        /// 商品总数量
        /// </summary>
        public int Quantity { get { return Items.Sum(o => o.Quantity); } }
        /// <summary>
        /// 商品总重量
        /// </summary>
        public decimal Weight { get { return Items.Sum(o => o.Weight); } }
        /// <summary>
        /// 商品总折扣
        /// </summary>
        public decimal Discount { get { return Items.Sum(o => o.Discount) + ShippingDiscounts.Sum(o => o.Value) + OrderSubTotalDiscounts.Sum(o => o.Value) + OrderTotalDiscounts.Sum(o => o.Value); } }
        /// <summary>
        /// 商品总金额(不含打折)
        /// </summary>
        public decimal SubTotal { get { return Items.Sum(o => o.Quantity * o.UnitPrice); } }
        /// <summary>
        /// 订单总金额
        /// </summary>
        public decimal Total { get { return SubTotal + ShippingCharge - Discount; } }
        /// <summary>
        /// 运输费
        /// </summary>
        public decimal ShippingCharge { get; set; }

        public IDictionary<int, decimal> OrderSubTotalDiscounts { get; set; }
        public IDictionary<int, decimal> OrderTotalDiscounts { get; set; }
        public IDictionary<int, decimal> ShippingDiscounts { get; set; }

        public UserAddress UserAddress { get; set; }
        public UserInvoice UserInvoice { get; set; }
        public IList<ShoppingCartItem> Items { get { return cartItems.Values.Cast<ShoppingCartItem>().ToList(); } }

        public void Add(Guid id, ShoppingCartItem cartItem)
        {
            if (cartItems.ContainsKey(id))
            {
                var temp = cartItems[id] as ShoppingCartItem;
                if (temp != null)
                {
                    if (temp.Quantity >= temp.OrderMaxQuantity)
                    {
                        temp.Message = string.Format("一个订单中最多只能购买{0}个", temp.OrderMaxQuantity);
                    }
                    else
                    {
                        temp.Message = string.Empty;
                        temp.Quantity += cartItem.Quantity;
                    }
                }
            }
            else
            {
                cartItems.Add(id, cartItem);
            }
        }

        public void Remove(Guid id)
        {
            var temp = cartItems[id] as ShoppingCartItem;
            if (temp == null) return;
            cartItems.Remove(id);
        }

        public void UpdateQuantity(Guid id, int quantity)
        {
            if (quantity < 1)
            {
                cartItems.Remove(id);
                return;
            }
            var temp = cartItems[id] as ShoppingCartItem;
            if (temp == null) return;

            if (quantity >= temp.OrderMaxQuantity)
            {
                temp.Quantity = temp.OrderMaxQuantity;
                temp.Message = string.Format("一个订单中最多只能购买{0}个", temp.OrderMaxQuantity);
            }
            else
            {
                temp.Quantity = quantity;
                temp.Message = string.Empty;
            }
        }

        public void Clear()
        {
            cartItems.Clear();
        }

        public ShoppingCart()
        {
            ShippingDiscounts = new Dictionary<int, decimal>();
            OrderTotalDiscounts = new Dictionary<int, decimal>();
            OrderSubTotalDiscounts = new Dictionary<int, decimal>();
        }

        public MiniShoppingCart ToMiniCart()
        {
            var items = Items.Select(o => new MiniShoppingCartItem { }).ToList();
            var miniCart = new MiniShoppingCart(Quantity, SubTotal, items);
            return miniCart;
        }

        public Order ToOrder()
        {
            var time = DateTime.Now;
            var identity = Identity.SkIdentity();
            var orderId = GenerateOrderId(time, identity.Id);
            var order = new Order {
                Id = orderId,
                UserId = identity.Id,
                Quantity = Quantity,
                SubTotal = SubTotal,
                ShippingCharge = ShippingCharge,
                Discount = Discount,
                Total = Total,
                Paid = 0,
                Refunded = 0,
                Weight = Weight,
                TraceCode = string.Empty,
                ShippingMethod = 0,
                PaymentMethod = 0,
                OrderStatus = OrderStatus.Pending,
                ShippingStatus = ShippingStatus.NotYetShipped,
                PaymentStatus = PaymentStatus.Pending,
                Expiration = DateTime.Now.AddHours(2),
                IpAddress = string.Empty,
                CreatedBy = Identity.Name,
                CreatedOn = time
            };
            var items = Items.Select((o, i) =>
                    new OrderItem {
                        Id = 0,
                        UserId = identity.Id,
                        OrderId = orderId,
                        ProductId = o.Id,
                        ProductVariantId = o.VariantId.ToString(),
                        ProductName = o.Name,
                        Discount = o.Discount,
                        Quantity = o.Quantity,
                        UnitPrice = o.UnitPrice,
                        CreatedBy = Identity.Name,
                        CreatedOn = time
                    });
            order.OrderItems = items.ToList();
            return order;
        }
        private static string GenerateOrderId(DateTime time, long userId)
        {
            return time.ToString("AyyyyMMddHHmmssfffffff") + userId;
        }

        //private static string GenerateOrderId(DateTime time)
        //{
        //    var array = new[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' };
        //    var year = time.ToString("yy");
        //    var month = array[time.Month - 1];
        //    var day = array[time.Day - 1];
        //    var hour = array[time.Hour - 1];
        //    var minute = time.ToString("mm");
        //    var second = time.ToString("ss");
        //    var ticks = time.ToString("fffffff");
        //    return year + month + day + hour + minute + second + ticks;
        //}
    }
}